home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Languguage OS 2
/
Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO
/
a_utils
/
perl
/
jinx.lha
/
jinx
< prev
next >
Wrap
Text File
|
1993-08-13
|
55KB
|
1,824 lines
#! /local/bin/perl
# jinx version 2.1 -- Copyright (c) 1990, Henk P. Penning.
# You may distribute under the terms of the GNU General Public License
# as specified in the README file that comes with the Jinx 2.1 kit.
sub QUIT
{ if ( $#_ >= 0 )
{ &move(0,0) ;
&addstr(@_[0]) ;
&clrtoeol ;
&frefresh ;
}
&quit() ;
}
sub quit
{ if ( $#_ >= 0 )
{ &showStatus(@_) ; }
&move($LINES-1,0) ;
&clrtoeol ;
&frefresh ;
&addlog("jinx closed.") ;
&endwin ;
&finishCterm ;
close(STDOUT) || warn "can't close STDOUT ($!)\n" ;
exit ;
}
sub showMenu
{ local(*menu) = @_ ;
return if $oldMenu eq *menu ;
$oldMenu = *menu ;
local($i) ;
&clrreg($firstMenuLine,$lastMenuLine) ;
for ($i=0 ; $i <= $#menu ; $i++)
{ &mvaddstr($firstMenuLine+$i,int(($COLS-length($menu[$i]))/2),
$menu[$i]) ;
}
&frefresh ;
}
sub ch2key
{ local($res) = @_ ;
$res = &ch2str($res) ;
if ( defined($keymap{$res}) )
{ return $keymap{$res} ; }
else
{ return $res ; }
}
sub getMappedKey { return &ch2key(&getchintR) ; }
sub showHelp
{ local(*menu) = @_ ;
&showCommand('help on (RET to quit):',' ') ;
for ( $res = &getMappedKey
; $res ne 'KEY_RET' && $res ne ' '
; $res = &getMappedKey
)
{ $res = defined($menu{$res})
? ( defined($menu{"help_$res"})
? $menu{"help_$res"} : 'no help'
)
: "not on the menu ($res)" ;
&showStatus($res) ;
&move($commandLine,$curposCommand) ;
}
}
sub showChoice
{ local(*menu,$default,$command) = @_ ;
local($res) ;
$command = "now what:" if $command eq '' ;
&showMenu(*menu) ;
&showCommand($command,$menu{$default}) ;
while ( 1 )
{ $res = &getMappedKey ;
&showStatus('') ;
$res = $default if $res eq 'KEY_RET' ;
last if defined $menu{$res} ;
if ( $res eq '?' )
{ &showHelp(*menu) ;
&showCommand($command,$menu{$default}) ;
next ;
}
&showStatusBeep("not on the menu ($res)") ;
&move($commandLine,$curposCommand) ;
&frefresh ;
}
$res = $menu{'KEY_TAB'} if $res eq 'KEY_TAB' ;
&addCommand($menu{$res}) if $res ne $default ;
return $res ;
}
sub showStatusList
{ local($_) ;
&showStatus(shift) if $#_ >= 0 ;
for ( @_ )
{ &showCommand('hit any key to continue: ') ;
&getchintR ;
&showStatus($_) ;
}
&frefresh ;
}
sub showStatus
{ local($_) = join('',@_) ;
return if $oldStatus eq $_ ;
if ( $_[0] eq '' )
{ &mvaddstr($statusLine,0,'>') ;
&clrtoeol ;
}
else
{ &show($_,0,$statusLine,0,$COLS-2,'> > ') ; }
$oldStatus = $_ ;
&frefresh ;
}
sub showStatusBeep
{ &showStatus ;
&beep ;
}
sub showJinxD
{ local($marked) = @_ ;
local($dbName,$mod) ;
$dbName = ($db ne '') ? $db : (($#name < 0) ? 'none' : 'no name') ;
$mod = ($#name < 0) ? '' : ($dirty ? ' [modified]' : ' [not modified]') ;
$marked = ( $marked > 0 ) ? " marked $marked" : '' ;
local($str) = "database: " . $dbName . $mod . $marked ;
if ( $str ne $oldJinxD )
{ &show($str,0,$jinxLineD,0,$COLS-2,'> > ') ;
$oldJinxD = $str ;
}
}
sub showJinxR
{ local($numRecs,$markInfo) = @_ ;
local($str) ;
if ( $numRecs >= 0 )
{ $str = sprintf("record %d of %d",$curr+1,$numRecs+1) ;
$str .= " $markInfo" if $markInfo ne '' ;
}
else
{ $str = 'no data' ; }
if ( $str ne $showJinxR )
{ &show($str,0,$jinxLineR,0,$COLS-2,'> > ') ;
$showJinxR = $str ;
}
}
sub showCommand
{ &mvaddstr($commandLine,0,join(' ',@_)) ;
&clrtoeol ;
$curposCommand = length($_[0])+1 ;
&move($commandLine,$curposCommand) if $#_ > 0 ;
&frefresh ;
}
sub addCommand
{ &mvaddstr($commandLine,$curposCommand,$_[0]) ;
&clrtoeol ;
&frefresh ;
}
sub checkDirty
{ return 1 if $dirty == 0 ;
local($dbname) = substr($db,rindex($db,'/')+1,1000) ;
local($times) = ($dirty == 1) ? 'once' : "$dirty times" ;
&showStatusBeep( (($db eq '') ? 'db' : $dbname) . " modified $times") ;
if ( &showChoice(*dirtyMenu,'n',"$command anyway?") eq 'y' )
{ return 1 ; }
else
{ &showStatus('no change') ;
$checkDirty = 1 ;
return 0 ;
}
}
sub doDescrMenu
{ local(*descr) = @_ ;
local(@name,@pat,@record) ;
local($res,$res1,$newPat,$next) = 'x' ;
&splitDescr(*descr,*name,*pat) ;
@record = @pat ;
while ( 1 )
{ $res = &showChoice(*doDescrMenu,$res) ;
if ( $res eq 'x' )
{ return 0 ; }
elsif ( $res eq 'f' )
{ &mkDescr(*descr,*name,*pat) ;
return 1 ;
}
elsif ( $res eq 'KEY_DOWN' && $curF < $#name )
{ $curF++ ; }
elsif ( $res eq 'KEY_UP' && $curF > 0 )
{ $curF-- ; }
elsif ( $res eq 'p' )
{ $res1 = &doUpdate(*updReMenu,'user',1,
*testRe,*quitUpd,*retPat) ;
if ( $res1 eq 'a' )
{ @pat = @record ; }
else
{ &showStatus('no change') ;
@record = @pat ;
}
}
elsif ( $res eq 'n' )
{ @record = @name ;
&unshowValues ;
&showRecord(*name,*record,$#data) ;
$res1 = &doUpdate(*updReMenu,'user',1,
*testNames,*quitUpd,*retNames) ;
if ( $res1 eq 'a' )
{ @name = @record ; }
else
{ &showStatus('no change') ; }
@record = @pat ;
&unshowRecord ;
}
else
{ &showStatusBeep("can't do it") ; }
&showRecord(*name,*record,$#data) ;
}
}
sub getNames
{ local(*name) = @_ ;
local($res,$cnt,@record,@res,$_,$i) = ('f',1) ;
@record = &emptyRecord($#name) ;
$Xr = 0 ;
$curF = 0 ;
&unshowValues ;
&showRecord(*name,*record,$#data) ;
while ( 1 )
{ $res = &showChoice(*getNamesMenu,$res) ;
if ( $res eq 'x' )
{ return 0 ; }
elsif ( $res eq 'f' )
{ @res = () ;
$i = 0 ;
for ( @record )
{ $res[$_-1] = $i if $_ > 0 ;
$i++ ;
}
return 1, @res ;
}
elsif ( $res eq 'KEY_DOWN' && $curF < $#name )
{ $curF++ ; }
elsif ( $res eq 'KEY_UP' && $curF > 0 )
{ $curF-- ; }
elsif ( $res eq 'KEY_RIGHT' && $record[$curF] == 0 )
{ $record[$curF] = $cnt++ ;
&showValue($record[$curF],$curF) ;
}
elsif ( $res eq 'KEY_LEFT' && $record[$curF] != 0 )
{ $cnt-- ;
if ( $record[$curF] == $cnt )
{ &showValue('',$curF) ; }
else
{ for ( @record )
{ $_-- if $_ != 0 && $_ > $record[$curF] ; }
&unshowValues ;
}
$record[$curF] = '' ;
}
elsif ( $res eq 'd' && $record[$curF] > 1 )
{ $i = 0 ;
for ( @record )
{ if ( $_ == $record[$curF] - 1 )
{ $_++ ; &showValue($_,$i) ; }
$i++ ;
}
&showValue(--$record[$curF],$curF) ;
}
elsif ( $res eq 'i' && $record[$curF] < $cnt-1 && $record[$curF] > 0 )
{ $i = 0 ;
for ( @record )
{ if ( $_ == $record[$curF] + 1 )
{ $_-- ; &showValue($_,$i) ; }
$i++ ;
}
&showValue(++$record[$curF],$curF) ;
}
elsif ( $res eq 's' && $cnt > 1 )
{ $i = 0 ;
@res = &emptyRecord($#name) ;
for ( @record )
{ if ( $_ > 0 )
{ $res[$_-1] = $name[$i] ; }
$i++ ;
}
&unshowValues ;
&showRecord(*name,*res,$#data) ;
&showCommand('hit any key to continue: ') ;
&getchintR ;
&unshowValues ;
}
else
{ &showStatusBeep("can't do it") ; }
&showRecord(*name,*record,$#data) ;
}
}
sub getFieldDescr
{ local($fName,$fPat,$fVal,$res) ;
($res,$fName) = &getStrFrom("fieldname:",*fName,$#fName) ;
if ( $res == 0 || $fName eq '' )
{ return '', "no name ; no change" ; }
elsif ( $fName !~ /$namePat/ )
{ return '', "name '$fName' not alfa-numeric ; no change" ; }
elsif ( grep(/^$fName$/,@name) != 0 )
{ return '', "name '$fName' already used ; no change" ; }
($res,$fPat) = &getStrFrom("pattern:",*sPat,$#sPat) ;
if ( $res == 0 )
{ return '', 'no change' ; }
elsif ( ! &testPat($fPat) )
{ return '', "$@ ; no change" ; }
($res,$fVal) = &getStrFrom("default value:",*fVal,$#fVal) ;
if ( $res == 0 )
{ return '', 'no change' ; }
elsif ( $fPat && $fVal !~ /$fPat/ )
{ return '', "default '$fVal' doesn't match '$fPat' ; no change" ; }
return $fName, $fPat, $fVal ;
}
sub searchNext
{ local(*row,$from,$sPat) = @_ ;
local($i) ;
&showStatus("searching ($sPat) ...") ;
for ($i=$from+1 ; $i<=$#row && $row[$i] !~ /$sPat/ ; $i++) { ; } ;
return($i,'found') if $i <= $#row ;
for ($i=0 ; $i<=$from && $row[$i] !~ /$sPat/ ; $i++) { ; } ;
return($i,'found only here') if $i == $from ;
return($i,'found') if $i < $from ;
return($from,'not found') ;
}
sub searchNextRecord
{ local(*row,$fromR,*record,$fromF,$sPat) = @_ ;
local($i,$j,@rec1) ;
&showStatus("searching ($sPat) ...") ;
for ($j=$fromF+1 ; $j<=$#record && $record[$j] !~ /$sPat/ ; $j++) { ; } ;
return($fromR,$j,'found in this record') if $j <= $#record ;
for ($i=$fromR+1 ; $i<=$#row && $row[$i] !~ /$sPat/ ; $i++) { ; } ;
if ( $i <= $#row )
{ @rec1 = split($;,$row[$i],$#record+1) ;
for ($j=0 ; $j<=$#rec1 && $rec1[$j] !~ /$sPat/ ; $j++) { ; } ;
return($i,$j,'found') if $j <= $#rec1 ;
return($i,$fromF,"error: record ($i) but no field in tail") ;
}
for ($i=0 ; $i<=$fromR && $row[$i] !~ /$sPat/ ; $i++) { ; } ;
return($fromR,$fromF,'not found') if $i > $fromR ;
@rec1 = split($;,$row[$i],$#record+1) ;
for ($j=0 ; $j<=$#rec1 && $rec1[$j] !~ /$sPat/ ; $j++) { ; } ;
return($i,$fromF,"error: record ($i) but no field in head") if $j > $#rec1 ;
return($i,$j,'found') if $i != $fromR ;
return($i,$j,'found only in this record') if $j != $fromF ;
return($i,$j,'found only here') if $j == $fromF ;
}
sub searchNextIndRecord
{ local(*ind,*row,$fromR,*record,$fromF,$sPat) = @_ ;
local($i,$j,@rec1) ;
&showStatus("searching ($sPat) ...") ;
for ($j=$fromF+1 ; $j<=$#record && $record[$j] !~ /$sPat/ ; $j++) { ; } ;
return($fromR,$j,'found in this record') if $j <= $#record ;
for ($i=$fromR+1 ; $i<=$#ind && $row[$ind[$i]] !~ /$sPat/ ; $i++) { ; } ;
if ( $i <= $#ind )
{ @rec1 = split($;,$row[$ind[$i]],$#record+1) ;
for ($j=0 ; $j<=$#rec1 && $rec1[$j] !~ /$sPat/ ; $j++) { ; } ;
return($i,$j,'found') if $j <= $#rec1 ;
return($i,$fromF,"error: record ($i) but no field in tail") ;
}
for ($i=0 ; $i<=$fromR && $row[$ind[$i]] !~ /$sPat/ ; $i++) { ; } ;
return($fromR,$fromF,'not found') if $i > $fromR ;
@rec1 = split($;,$row[$ind[$i]],$#record+1) ;
for ($j=0 ; $j<=$#rec1 && $rec1[$j] !~ /$sPat/ ; $j++) { ; } ;
return($i,$fromF,"error: record ($i) but no field in head") if $j > $#rec1 ;
return($i,$j,'found') if $i != $fromR ;
return($i,$j,'found only in this record') if $j != $fromF ;
return($i,$j,'found only here') if $j == $fromF ;
}
sub setDataYXd
{ local($numNames) = @_ ;
if ( $curr < $numFieldLines )
{ $Yd = 0 ; }
elsif ( $curr > $#data - $numFieldLines )
{ $Yd = $#data - $numFieldLines + 1 ; }
else
{ $Yd = $curr - int(($numFieldLines-1)/2) ; }
if ( $colView )
{ $maxXd = $numNames ; }
else
{ $maxStrlenD = &maxStrlen(*data,$Yd,$Yd+$numFieldLines-1) ;
$maxXd = $maxStrlenD - $numInfoCols + 2 ;
}
$Xd = &max(0,&min($maxXd,$Xd)) ;
}
sub unshowData
{ $oldYd = undef ; }
sub showData
{ local(*data,$numNames) = @_ ;
local($i) ;
&showJinxR($#data) ;
if ( ! defined($oldYd) || $Yd > $curr || $curr >= $Yd + $numFieldLines )
{ &setDataYXd($numNames) ; }
if ( ! defined($oldYd) )
{ &setDataScreen(*data) ;
&showDataScreen(*data,$Yd,$Xd,$curr) ;
}
elsif ( $Yd != $oldYd || $Xd != $oldXd )
{ &showDataScreen(*data,$Yd,$Xd,$curr) ; }
elsif ( $#data >= 0 )
{ &moveCursorScreen($curr,$Yd) ; }
$oldYr = undef ;
$oldYd = $Yd ;
$oldXd = $Xd ;
&frefresh ;
}
sub setYr
{ if ( $curF < $numFieldLines )
{ $Yr = 0 ; }
elsif ( $curF > $#record - $numFieldLines )
{ $Yr = $#record - $numFieldLines + 1 ; }
else
{ $Yr = $curF - int(($numFieldLines-1)/2) ; }
}
sub setXr
{ @strlenR = @record ;
$maxStrlenR = &max(grep($_=length,@strlenR)) ;
$maxXr = $maxStrlenR - $numValueCols + 2 ;
$Xr = &max(0,&min($Xr,$maxXr)) ;
}
sub unshowRecord
{ $oldYr = undef ; }
sub unshowValues
{ $oldXr = undef ; }
sub showValue
{ local($value,$curF) = @_ ;
&showValueScreen($value,$curF,$Yr) ;
}
sub editValue
{ local($newField,$curF) = @_ ;
local(@res) ;
@res = &editValueScreen($newField,$curF,$Yr) ;
return @res ;
}
sub showRecord
{ local(*name,*record,$numRecs,$markInfo) = @_ ;
&showJinxR($numRecs,$markInfo) ;
if ( ! defined($oldYr) || $Yr > $curF || $curF >= $Yr + $numFieldLines )
{ &setYr ; }
if ( ! defined($oldYr) )
{ &setKeyScreen(*name) ;
&showKeysScreen(*name,$Yr,0,$curF) ;
&setXr ;
&showValuesScreen(*record,$Yr,$Xr) ;
}
elsif ( $Yr != $oldYr )
{ &showKeysScreen(*name,$Yr,0,$curF) ;
&setXr ;
&showValuesScreen(*record,$Yr,$Xr) ;
}
else
{ if ( ! defined($oldXr) || $Xr != $oldXr )
{ &setXr ;
&showValuesScreen(*record,$Yr,$Xr) ;
}
if ( $curF != $oldCurF )
{ &moveCursorScreen($curF,$Yr) ; }
}
$oldYd = undef ;
$oldYr = $Yr ;
$oldXr = $Xr ;
$oldCurF = $curF ;
&frefresh ;
}
sub showTest
{ local(*name,*pat,*record) = @_ ;
local($_,@res,$i) ;
@res = &doTest(*record,*pat) ;
do { &showStatus("ok") ; return ; } if $#res < 0 ;
for ( @res )
{ $curF = $_ ;
&showRecord(*name,*record,$#data) ;
&showStatusBeep("field doesn't match $pat[$_]") ;
last if $i++ == $#res ;
&showCommand('hit any key to continue: ') ;
&getchintR ;
}
}
sub showTestAll
{ local(*name,*pat,*data) = @_ ;
local($c,$tmpCurr,@record,@res) = 'n' ;
$tmpCurr = $curr ;
showTestAll:
for $curr ( $tmpCurr..$#data,0..$tmpCurr-1 )
{
showTest:
while ( 1 )
{ @record = split(/$;/,$data[$curr],$#name+1) ;
@res = &doTest(*record,*pat) ;
next showTestAll if $#res < 0 ;
&unshowValues ;
showField: for ( @res )
{ $curF = $_ ;
&showRecord(*name,*record,$#data) ;
&showStatusBeep("field doesn't match $pat[$_]") ;
$c = &showChoice(*testMenu,$c) ;
last showField if $c =~ /[quN]/ ;
}
if ( $c eq 'x')
{ &showStatus('exit Test All') ;
return $curr ;
}
elsif ( $c eq 'u' )
{ $c = &doUpdate(*updMatchMenu,'user',1,
*testUpd,*quitUpd,*retUpd) ;
if ( $c eq 'a' )
{ $data[$curr] = $record ;
$dirty++ ;
&showJinxD() ;
}
$c = 'n' ;
redo showTest ;
}
else
{ last showTest ; }
}
&showStatus('Testing All ...') ;
}
&showStatus('tested all') ;
return $curr ;
}
sub getStrFrom
{ local($command,*alts,$default) = @_ ;
local($x,$str,$ret) ;
$default = $#alts if $#_ < 2 ;
push(@alts,'') ;
$default = &max(0,&min($default,$#alts)) ;
&showMenu(*searchMenu) ;
$command .= ' ' ;
$x = length($command) ;
&showCommand($command) ;
while ( 1 )
{ $str = $alts[$default] ;
($str,$res) = &edit($str,0,$commandLine,$x,$COLS-$x-2,'|<>|') ;
# replace previous line by next line if LAST-ROW-COL-BUG |
# ($str,$res) = &edit($str,0,$commandLine,$x,$COLS-$x-3,'|<>|') ;
$res = &ch2key($res) ;
if ( $res eq 'KEY_TAB' )
{ $ret = 0 ; $str = '' ; last ; }
elsif ( $res eq 'KEY_RET' )
{ $ret = 1 ; last ; }
elsif ( $res eq 'KEY_UP' && $default > 0 )
{ $default-- ; }
elsif ( $res eq 'KEY_DOWN' && $default < $#alts )
{ $default++ ; }
else
{ &showStatusBeep("can't do $res") ; }
}
pop(@alts) while $#alts >= 0 && ! $alts[$#alts] ;
push(@alts,$str) if $str && ( $#alts < 0 || $str ne $alts[$#alts] ) ;
return $ret, $str ;
}
sub getGoto
{ local($curr) = @_ ;
local($res,$goto) = &getStrFrom('Where:',*gotos,$#gotos) ;
return '' unless $res ;
$goto .= '' ;
return $goto-1 if $goto =~ /^[0-9]+$/ ;
return $curr+$1 if $goto =~ /^\+([0-9]+)$/ ;
return $curr-$1 if $goto =~ /^\-([0-9]+)$/ ;
return '' ;
}
sub doPeek
{ local(*name,$db,*name1,*data1) = @_ ;
local($_,@vals,@common,@common1,@new,@empty) ;
&mkInvert(*name) ;
&mkInvert(*name1) ;
for ( @name1 )
{ if ( defined $name{$_} )
{ push(@common,$name{$_}) ;
push(@common1,$name1{$_}) ;
}
else
{ $_ = '__' . $_ ; }
}
return(0,"no field in common ; no change") if $#common < 0 ;
$_ = ( $#common ? 'fields' : 'field' ) ;
&showStatus("relevant $_ : " . join(',',@name1[@common1]) ) ;
@vals = 0..$#data1 ;
$db = "Peeking in " . substr($db,rindex($db,'/')+1,1000) ;
($res,@vals) = &selectFrom($db,*name1,*data1,@vals) ;
if ( $res eq 'x' || $#vals < 0 )
{ return(0,'no change') ; }
else
{ @empty = &emptyRecord($#name) ;
for ( @vals )
{ @new = @empty ;
@new[@common] = (split(/$;/,$data1[$_],$#name1+1))[@common1] ;
push(@data,join($;,@new)) ;
}
$_ = $#vals+1 ;
$_ = ( $_ == 1 ) ? 'one record' : "$_ records" ;
return(1,"added $_ (at the end)") ;
}
}
sub doRead
{ local(*name,$db,*name1,*data1) = @_ ;
local($_,$i,@vals,@common,@common1,@new,@empty,%key,%key1,$key1) ;
&mkInvert(*name) ;
&mkInvert(*name1) ;
for ( @name1 )
{ if ( defined $name{$_} )
{ push(@common,$name{$_}) ;
push(@common1,$name1{$_}) ;
}
else
{ $_ = '__' . $_ ; }
}
return(0,"no field in common ; no change") if $#common < 0 ;
for ( @data )
{ $key{join($;,(split(/$;/,$_))[@common])} = 1 ; }
$i = 0 ;
for ( @data1 )
{ $key1 = join($;,(split(/$;/))[@common1]) ;
push(@vals,$i) unless defined($key{$key1}) || defined($key1{$key1}) ;
$key1{$key1}++ ;
$i++ ;
}
return(0,"no new records to Read ; no change") if $#vals < 0 ;
$_ = ( $#common ? 'fields' : 'field' ) ;
&showStatus("relevant $_ : " . join(',',@name1[@common1]) ) ;
$db = "Reading in " . substr($db,rindex($db,'/')+1,1000) ;
($res,@vals) = &selectFrom($db,*name1,*data1,@vals) ;
if ( $res eq 'x' || $#vals < 0 )
{ return(0,'no change') ; }
else
{ @empty = &emptyRecord($#name) ;
for ( @vals )
{ @new = @empty ;
@new[@common] = (split(/$;/,$data1[$_],$#name1+1))[@common1] ;
push(@data,join($;,@new)) ;
}
$_ = $#vals+1 ;
$_ = ( $_ == 1 ) ? 'one record' : "$_ records" ;
return(1,"added $_ (at the end)") ;
}
}
# doKeyTest returns 0 if error or exit
# doKeyTest returns 1 if all uniq
# doKeyTest returns x if x+1 doubles appeared
sub doKeyTest
{ local(*data,*name,*fields) = @_ ;
local($_,$i,$res,@dvals,@vals,$vals,@delete,%key,@prefix) ;
local(@names) = @name ;
local($ret) = 1 ;
if ( $#fields >= 0 )
{ for ( 0..$#names ) { $prefix[0+$_] = '__' ; }
for ( @fields ) { $prefix[0+$_] = '' ; }
$i = 0 ;
for ( @names ) { $_ = $prefix[$i++] . $_ ; }
$i = 0 ;
for ( @data )
{ $key{join($;,(split(/$;/,$_))[@fields])} .= ( $i++ . ',' ) ; }
}
else
{ for ( @data ) { $key{$_} .= ( $i++ . ',' ) ; }
@fields = 0..$#names ;
}
local($db) = "SELECT TO DELETE" ;
keyTest:
for ( sort keys %key )
{ $vals = $key{$_} ;
chop $vals ;
next keyTest unless $vals =~ /,/ ;
$ret++ ;
next keyTest if $res eq 'f' ;
@vals = split(/,/,$vals) ;
keyTestMenu:
while ( 1 )
{ &showStatus($#vals+1, " records have key '", &intext($_), "'") ;
$res = &showChoice(*keyTestMenu,'n') ;
if ( $res eq 's' )
{ ($res,@dvals) = &selectFrom($db,*names,*data,@vals) ;
if ( $res eq 'x' )
{ next keyTestMenu ; }
elsif ( $res eq 'a' )
{ push(@delete,@dvals) ;
next keyTest ;
}
else
{ &showStatus('Huh ?') ; }
}
elsif ( $res eq 'n' )
{ next keyTest ; }
elsif ( $res eq 'f' )
{ next keyTest ; }
elsif ( $res eq 'x' )
{ @delete = () ;
$ret = 0 ; ;
last keyTest ;
}
else
{ &showStatus('Huh ?') ; }
}
}
&unshowRecord ;
return $ret, @delete ;
}
sub selectFrom
{ local($db,*name2,*data2,@vals) = @_ ;
local($c,$curr,$Yr,$Xr,$maxStrlenR,$curF,$dirty,$i) ;
local($marked,@sub,@unmarked,%marked,$markInfo) ;
local($res,$res1,$valscurr,$sPat) ;
$curr = 0 ;
$c = 'n' ;
$Xr = 0 ;
&unshowRecord ;
while ( 1 )
{ $valscurr = $vals[$curr] ;
@record = split(/$;/,$data2[$valscurr],$#name2+1) ;
$markInfo = ( defined $marked{$valscurr} ) ? '** MARKED **' : '' ;
&showJinxD($dirty) ;
&showRecord(*name2,*record,$#vals,$markInfo) ;
$c = &showChoice(*selectFromMenu,$c) ;
if ( $c eq "x" )
{ return('x') ; }
elsif ( $c eq "s" )
{ return('a',$valscurr) ; }
elsif ( $c eq "S" )
{ return('a', keys %marked ) ; }
elsif ( $c eq "t" )
{ if ( defined $marked{$valscurr} )
{ delete $marked{$valscurr} ; $dirty-- ; }
else
{ $marked{$valscurr} = 1 ; $dirty++ ; }
}
elsif ( $c eq "T" )
{ for $i ( @vals )
{ if ( defined $marked{$i} )
{ delete $marked{$i} ; $dirty-- ; }
else
{ $marked{$i} = 1 ; $dirty++ ; }
}
}
elsif ( $c eq "C" )
{ %marked = () ;
$dirty = 0 ;
}
elsif ( $c eq 'M' && $dirty > $#data2 )
{ &showStatusBeep('every record is Marked') ; }
elsif ( $c eq 'M' )
{ @record = &emptyRecord($#name2) ;
$Xr = 0 ;
$curF = 0 ;
&unshowValues ;
&showRecord(*name2,*record,$#data2) ;
if ( &doUpdate(*updReMenu,'user',1,
*testRe,*quitUpdAdd,*retRe) eq 'a'
)
{ &showStatus('Marking ...') ;
@unmarked = grep( ! defined $marked{$_}, @vals) ;
($res,$res1) = &doAddMark(*data2,*record,*marked,*unmarked) ;
if ( $res )
{ &showStatus("marked ",$res1+0) ;
$dirty += $res1 ;
}
&showStatus($res1) if ! $res ;
}
else
{ &showStatus('no change') ; }
&unshowValues ;
}
elsif ( $c eq 'U' && $dirty == 0 )
{ &showStatusBeep('every record is Unmarked') ; }
elsif ( $c eq 'U' )
{ @record = &emptyRecord($#name2) ;
$Xr = 0 ;
$curF = 0 ;
&unshowValues ;
&showRecord(*name2,*record,$#data2) ;
if ( &doUpdate(*updReMenu,'user',1,
*testRe,*quitUpdAdd,*retRe) eq 'a'
)
{ &showStatus('unMarking ...') ;
@sub = keys %marked ;
($res,$res1) = &doDelMark(*data2,*record,*marked,*sub) ;
if ( $res )
{ &showStatus("unmarked ",0+$res1) ;
$dirty -= $res1 ;
}
&showStatus($res1) if ! $res ;
}
else
{ &showStatus('no change') ; }
&unshowValues ;
}
elsif ( $c eq "n" && $curr < $#vals )
{ $curr++ ;
&unshowValues ;
}
elsif ( $c eq "p" && $curr > 0 )
{ $curr-- ;
&unshowValues ;
}
elsif ( $c eq "/" )
{ ($res,$sPat) = &getStrFrom('pattern:',*sPat,$#sPat) ;
if ( $res == 0 || $sPat eq '' )
{ &showStatus('no change') ; }
elsif ( ! &testPat($sPat) )
{ &showStatus($@) ; }
else
{ ($curr,$curF,$res) =
&searchNextIndRecord(*vals,*data2,$curr,*record,$curF,$sPat) ;
&showStatus($res) ;
&unshowValues if $res eq 'found' ;
}
}
elsif ( $c eq ";" && $#sPat >= 0 )
{ $sPat = $sPat[$#sPat] ;
if ( ! &testPat($sPat) )
{ &showStatus($@) ; }
else
{ ($curr,$curF,$res) =
&searchNextIndRecord(*vals,*data2,$curr,*record,$curF,$sPat) ;
&showStatus($res) ;
&unshowValues if $res eq 'found' ;
}
}
elsif ( $c eq ">" && $dirty > ( defined $marked{$valscurr} ) )
{ for ( $i=$curr+1 ;
$i <= $#vals && ! defined $marked{$vals[$i]} ;
$i++ ) { ; }
if ( $i > $#vals )
{ &showStatusBeep('not found') ; }
else
{ &showStatus('found') ;
$curr = $i ;
&unshowValues ;
}
}
elsif ( $c eq "<" && $dirty > ( defined $marked{$valscurr} ) )
{ for ( $i=$curr-1 ;
$i >= 0 && ! defined $marked{$vals[$i]} ;
$i-- ) { ; }
if ( $i < 0 )
{ &showStatusBeep('not found') ; }
else
{ &showStatus('found') ;
$curr = $i ;
&unshowValues ;
}
}
elsif ( $c eq ")" && ($#vals - $dirty >= (!defined($marked{$valscurr}))) )
{ for ( $i=$curr+1 ;
$i <= $#vals && defined $marked{$vals[$i]} ;
$i++ ) { ; }
if ( $i > $#vals )
{ &showStatusBeep('not found') ; }
else
{ &showStatus('found') ;
$curr = $i ;
&unshowValues ;
}
}
elsif ( $c eq "(" && ($#vals - $dirty >= (!defined($marked{$valscurr}))) )
{ for ( $i=$curr-1 ;
$i >= 0 && defined $marked{$vals[$i]} ;
$i-- ) { ; }
if ( $i < 0 )
{ &showStatusBeep('not found') ; }
else
{ &showStatus('found') ;
$curr = $i ;
&unshowValues ;
}
}
elsif ( $c eq "g" && ($res = &getGoto($curr)) ne '' &&
0 <= $res && $res <= $#data2 )
{ do { $curr = $res ; &unshowValues ; } if $res != $curr ;
$Xr = 0 ;
}
elsif ( $c eq 'KEY_UP' && $curF > 0 )
{ $curF-- ; }
elsif ( $c eq 'KEY_DOWN' && $curF < $#name2 )
{ $curF++ ; }
elsif ( $c eq 'KEY_LEFT' && $Xr > 0 )
{ $Xr = &max($Xr-1-int(($numValueCols-2)/3),0) ; }
elsif ( $c eq 'KEY_RIGHT' && $Xr < $maxXr )
{ $Xr = &min($Xr+1+int(($numValueCols-2)/3),$maxXr) ; }
else
{ &showStatusBeep("can't do it") ; }
}
}
sub doUpdate
{ local(*menu,$modeDef,$acceptDef,*testUp,*quitUp,*retUp) = @_ ;
local($newField,$res,$c) ;
local($mode) = $modeDef ;
local(@accept) = @record ;
for (@accept) { $_ = $acceptDef ; }
while (1)
{ $newField = $record[$curF] if $res ne 'edit' ;
if ( $mode eq 'user' || $res eq 'edit' )
{ &showMenu(*updateMenu) ;
&showCommand("now what:","edit, rule: $pat[$curF]") ;
($newField,$res) = &editValue($newField,$curF) ;
$res = &ch2key($res) ;
&showStatus('') ;
}
else
{ $res = 'KEY_TAB' ; }
if ( $record[$curF] eq $newField && $accept[$curF] )
{ ; }
elsif ( &testUp($newField,$curF,$res) )
{ $record[$curF] = $newField ;
$accept[$curF] = $acceptDef ;
}
else
{ &showStatusBeep($testUp) ;
$c = &showChoice(*menu,'e') ;
if ( $c eq "e" )
{ $res = 'edit' ; }
elsif ( $c eq "a" )
{ $record[$curF] = $newField ;
$accept[$curF] = $acceptDef ;
}
elsif ( $c eq "f" )
{ &showValue($record[$curF],$curF) ;
if ( $accept[$curF] || &testUp($record[$curF],$curF) )
{ &showStatus('') ; }
else
{ $newField = $record[$curF] ;
$res = 'edit' ;
&showStatusBeep("this isn't ok either") ;
}
}
elsif ( $c eq "x" )
{ $res = 'exit' ;
&unshowValues ;
}
}
if ( $res eq 'exit' )
{ return('f') ; }
elsif ( $res eq 'edit' )
{ ; }
elsif ( &quitUp($res,$curF) )
{ $record = join($;,@record) ;
$res = &retUp ;
return $res if $res ne 'e' ;
$res = 'edit' ;
}
elsif ( $res eq 'KEY_UP' && $curF > 0 )
{ $curF-- ; }
elsif ( ( $res eq 'KEY_TAB' || $res eq 'KEY_RET' || $res eq 'KEY_DOWN' )
&& $curF < $#name )
{ $curF++ ; }
else
{ &beep ; }
}
continue
{ &showRecord(*name,*record,$#data) ; }
}
sub testRe
{ local($value,$curF,$next) = @_ ;
return 1 if &testPat($value) ;
$testRe = $@ ;
return 0 ;
}
sub testEx
{ local($value,$curF,$next) = @_ ;
if ( $value =~ /^\s+$/ )
{ $testEx = 'empty expression' ;
return 0 ;
}
elsif ( ! &testExpr($value) )
{ $testEx = $@ ;
return 0 ;
}
return 1 ;
}
sub testNames
{ local($value,$curF,$next) = @_ ;
if ( $value !~ /$namePat/ )
{ $testNames = "name '$value' not alfa-numeric" ;
return 0 ;
}
local($res) ; $res = grep(/^$value$/,@record) ;
if ( $res == 1 && $value ne $record[$curF] )
{ $testNames = "name '$value' is used" ;
return 0 ;
}
return 1 ;
}
sub testUpd
{ local($value,$curF,$next) = @_ ;
return 1 if $pat[$curF] eq '' || $value =~ /$pat[$curF]/ ;
$testUpd = "$name[$curF] doesn\'t match $pat[$curF]" ;
return 0 ;
}
sub quitUpd
{ local($next,$curF) = @_ ;
return $next eq 'KEY_TAB' ;
}
sub quitUpdAdd
{ local($next,$curF) = @_ ;
return 1 if $next eq 'KEY_TAB' && $curF == $#name ;
$mode = ($next eq 'KEY_TAB') ? 'system' : 'user' ;
return 0 ;
}
sub retRe
{ local($res) =
( grep(/./,@record) == 0 ) ? 'a' : &showChoice(*updateXMenu,'a') ;
$mode = 'user' if $res eq 'e' ;
return $res ;
}
sub retEx
{ local($res) =
( grep(/./,@record) == 0 ) ? 'f' : &showChoice(*updateXMenu,'a') ;
$mode = 'user' if $res eq 'e' ;
return $res ;
}
sub retNames
{ local($res) = ( $record eq join("$;",@name) )
? 'f' : &showChoice(*updateXMenu,'a') ;
return $res ;
}
sub retPat
{ local($res) ;
if ( $record eq join("$;",@pat) )
{ $res = 'f' ; }
else
{ $res = &showChoice(*updateXMenu,'a') ;
&unshowValues if $res eq 'f' ;
}
return $res ;
}
sub retUpd
{ if ( $data[$curr] eq $record )
{ return 'f' ; }
else
{ local($res) = &showChoice(*updateXMenu,'a') ;
&unshowValues if $res eq 'f' ;
return $res ;
}
}
sub retUpdAdd
{ local($res) = &showChoice(*updateXMenu,'a') ;
&unshowValues if $res eq 'f' ;
$mode = 'user' if $res eq 'e' ;
return $res ;
}
sub doMetaMenu
{ local($c,$command,$Yd,$Xd,$Yr,$Xr,$curr,$maxStrlenD,$str,$res,$found) ;
local($colView) ;
$c = ($#name < 0) ? 'o' : 'i' ;
&unshowData ;
while( 1 )
{ $found = 1 ;
&showJinxD() ;
&showData(*data,$#name) ;
$c = &showChoice(*metaMenu,$c) ;
$command = $metaMenu{$c} ;
if ( $c eq '' || $c eq "Q" )
{ &quit('no update') if $dirty ;
&quit('normal quit') ;
}
elsif ( $c eq "q" && &checkDirty )
{ &quit('jinx says: bye bye') ; }
elsif ( $c eq "p" && $curr > 0 )
{ $curr = &max(0,$curr-$numFieldLines) ; }
elsif ( $c eq "n" && $curr < $#data )
{ $curr = &min($#data, $curr + $numFieldLines) ; }
elsif ( $c eq 'KEY_UP' && $curr > 0 )
{ $curr-- ; }
elsif ( $c eq 'KEY_DOWN' && $curr < $#data )
{ $curr++ ; }
elsif ( $c eq 'KEY_LEFT' && $Xd > 0 )
{ if ( $colView )
{ $Xd-- ; }
else
{ $Xd = &max($Xd-1-int(($numInfoCols-2)/3),0) ; }
}
elsif ( $c eq 'KEY_RIGHT' && $Xd < $maxXd )
{ if ( $colView )
{ $Xd++ ; }
else
{ $Xd = &min($Xd+1+int(($numInfoCols-2)/3),$maxXd) ; }
}
elsif ( $c eq "g" && $#name >= 0 && $#data >= 0 &&
( $res = &getGoto($curr) ) ne '' &&
0 <= $res && $res <= $#data )
{ $curr = $res ;
$Xd = 0 ;
}
elsif ( $c eq "/" && $#name >= 0 && $#data >= 0)
{ ($res,$sPat) = &getStrFrom('pattern:',*sPat,$#sPat) ;
if ( $res == 0 || $sPat eq '' )
{ &showStatus('no change') ; }
elsif ( ! &testPat($sPat) )
{ &showStatus($@) ; }
else
{ ($curr,$res) = &searchNext(*data,$curr,$sPat) ;
&showStatus($res) ;
}
}
elsif ( $c eq ";" && $#name >= 0 && $#data >= 0 && $#sPat >= 0 )
{ $sPat = $sPat[$#sPat] ;
if ( ! &testPat($sPat) )
{ &showStatus($@) ; }
else
{ ($curr,$res) = &searchNext(*data,$curr,$sPat) ;
&showStatus($res) ;
}
}
elsif ( $c eq "i" && $#name >= 0 )
{ $curr = &doMainMenu(*name,*pat,*data,*ddata,$curr,*mainUpdate) ;
if ( $curr eq 'Q' )
{ if ( $dirty )
{ &quit('quit without update') ; }
else
{ &quit("normal quit ; database wasn't modified") ; }
}
$curr = &min($#data,$curr) ;
$Xd = 0 ;
}
elsif ( $c eq "o" && &checkDirty )
{ ($res,$str) = &getStrFrom('open:',*openAs,$currDb) ;
if ( $res == 0 )
{ &showStatus('no change') ; }
else
{ $currDb++ ;
&showStatus('opening ...') ;
($res,@res) = &openCurrDb($str) ;
&showStatusList(@res) ;
if ( $res )
{ push(@saveAs,$str)
if $#saveAs < 0 || $saveAs[$#saveAs] ne $str ;
$curr = &min($#data,0) ;
$Xd = 0 ;
$dirty = 0 ;
@ddata = () ;
&unshowData ;
}
}
}
elsif ( $c eq "C" && $#name >= 0 && &checkDirty )
{ &showStatus("database wasn't modified") if ! $dirty ;
$dirty = 0 ;
$db = '' ;
@data = () ;
@ddata = () ;
@descr = () ;
@name = () ;
@pat = () ;
$curr = -1 ;
&unshowData ;
}
elsif ( $c eq "V" )
{ $colView = ! $colView ;
$Xd = 0 ;
&unshowData ;
}
else { $found = 0 ; }
if ( $found )
{ ; }
elsif ( $c eq "s" && $#name >= 0)
{ if ( $db eq '' )
{ &showStatus('no name ; Save as ...') ; }
elsif ( ! $dirty)
{ &showStatus('no modification since last update') ; }
else
{ &showStatus('saving ...') ;
($res,$resStr) = &putInfo(*data,$db,'dat') ;
&showStatus($resStr) ;
$dirty = 0 if $res ;
}
}
elsif ( $c eq "S" && $#name >= 0)
{ push(@saveAs,'') ;
($res,$str) = &getStrFrom('Save as:',*saveAs) ;
if ( $res == 0 || $str eq '')
{ &showStatus('not saved') ; }
else
{ if ( ! -e "$str.des" ||
do { &showStatusBeep("database $str exists") ;
&showChoice(*dirtyMenu,'n','write anyway ?') eq 'y' ;
}
)
{ &showStatus('Saving ...') ;
($resDescr,$resStr1) = &putInfo(*descr,$str,'des') ;
if ( ! $resDescr )
{ &showStatus($resStr1) ; }
else
{ ($resData, $resStr2) = &putInfo(*data,$str,'dat') ;
&showStatus("$resStr1; $resStr2") ;
if ( $db eq '' && $resData )
{ $db = $str ;
$dirty = 0 ;
}
}
}
else
{ &showStatus("no change") ; }
}
}
elsif ( $c eq "O" && $#name >= 0 && $#data >= 0 )
{ &showStatus('select sort keys (or finish to sort whole records)') ;
($res,@record) = &getNames(*name) ;
if ( $res )
{ &showStatus('sorting ...') ;
($res,@errors) = &doSort(*data,*record) ;
&showStatusList(@errors) ;
do { $curr = 0 ; $dirty++ ; } if $res ;
}
else
{ &showStatus('no change') ; }
}
elsif ( $c eq "P" && $#name >= 0 && &checkDirty )
{ &showStatus('select columns to project') ;
($res,@record) = &getNames(*name) ;
if ( $res )
{ &showStatus('Projecting ...') ;
($res,@errors) = &doProject(*descr,*name,*pat,*data,*record) ;
&showStatusList(@errors) ;
if ( $res )
{ &doProjectData(*ddata,*record) ;
$dirty = 1 ;
$curr = &min($#data,0) ;
$Xd = 0 ;
$db = '' ;
}
}
else
{ &showStatus('no change') ; }
}
elsif ( $c eq "D" && $#name >= 0 )
{ @record = @pat ;
$Xr = 0 ;
$curF = 0 ;
&showRecord(*name,*record,$#data) ;
@descr1 = @descr ;
if ( &doDescrMenu(*descr1) &&
join("$;",sort @descr) ne join("$;",sort @descr1) )
{ @descr = @descr1 ;
&splitDescr(*descr,*name,*pat) ;
$db = '' ;
}
else
{ &showStatus('no change') ; }
}
elsif ( $c eq "J" && $#name >= 0 && &checkDirty )
{ ($res,$str) = &getStrFrom('with what?',*joinList,$#joinList) ;
if ( $res == 0 )
{ &showStatus('no change') ; }
else
{ &showStatus('opening ...') ;
($res,@errors) = &openDb($str,*descr2,*data2,*name2,*pat2) ;
&showStatusList(@errors) ;
if ( $res == 0 )
{ if ( $Xd )
{ $Xd = 0 ;
&unshowData ;
}
&showStatus('Joining ...') ;
($res,@errors) = &doJoin(*descr,*data,*descr2,*data2,'','') ;
&showStatusList(@errors) ;
if ( $res )
{ &splitDescr(*descr,*name,*pat) ;
$dirty = 1 ;
@ddata = () ;
$curr = &min($#data,0) ;
$db = '' ;
&unshowData ;
}
}
}
}
elsif ( $c eq "G" && &checkDirty )
{ if ( do { ($res,$str) =
&getStrFrom('Guess what?',*guessList,$#guessList) ;
$res == 0 || $str eq '' ;
}
)
{ &showStatus('no change') ; }
elsif ( ! -r $str )
{ &showStatus("can't read $str") ; }
elsif ( do { ($res,$pat) =
&getStrFrom('separator?',*sepList,$#sepList) ;
$res == 0 ;
}
)
{ &showStatus('no change') ; }
else
{ &showStatus('Guessing ...') ;
($res,$errors) = &doGuessData($str,$pat,*data1) ;
&showStatus($errors) ;
if ( $res != 0 )
{ @data = @data1 ;
&doGuessDescr($res,*descr) ;
&splitDescr(*descr,*name,*pat) ;
$dirty = 1 ;
@ddata = () ;
$curr = &min($#data,0) ;
$Xd = 0 ;
$db = '' ;
&unshowData ;
}
}
}
elsif ( $c eq "A" && &checkDirty )
{ ($fName,$fPat,$fVal) = &getFieldDescr ;
if ( $fName ne '' )
{ &showStatus('Adding ...') ;
&addFieldNP(*descr,*name,$fName,*pat,$fPat) ;
for $data ( @data ) { $data .= $; . $fVal ; }
for $data ( @ddata ) { $data .= $; . $fVal ; }
$db = '' ;
$dirty++ ;
&unshowData ;
}
else
{ &showStatusBeep($fPat) ; }
}
elsif ( $c eq "T" && $#data >= 0 )
{ &showStatus('Testing All ...') ;
$curr = &showTestAll(*name,*pat,*data) ;
}
elsif ( $checkDirty )
{ $checkDirty = 0 ; }
else
{ &showStatusBeep("can't do it") ; }
}
}
sub mainUpdate
{ local($c) = @_ ;
if ( $c eq 'u' )
{ &doUpdate(*updMatchMenu,'user',1,*testUpd,*quitUpd,*retUpd) ; }
else
{ &doUpdate(*updMatchMenu,'user',0,*testUpd,*quitUpdAdd,*retUpdAdd) ; }
}
sub doMainMenu
{ local(*name,*pat,*data,*ddata,$curr,*onUpdate) = @_ ;
local($c,$Yr,$Xr,$maxStrlenR,$curF,@ndata,$found) ;
$curr = -1 if $#data < 0 ;
$c = ( $#data < 0 ) ? 'a' : 'n' ;
$Xr = 0 ;
&unshowRecord ;
while ( 1 )
{ $found = 1 ;
if ($curr >= 0)
{ @record = split(/$;/,$data[$curr],$#name+1) ; }
else
{ @record = &emptyRecord($#name) ; }
&showJinxD() ;
&showRecord(*name,*record,$#data) ;
$c = ( $#data == -1 ) ? 'a' : 'n' if $c eq 'd' ;
$c = &showChoice(*mainMenu,$c) ;
if ( $c eq '' || $c eq "Q" )
{ return('Q') ; }
elsif ( $c eq "f" )
{ return($curr) ; }
elsif ( $c eq "g" && $#data >= 0 &&
($res = &getGoto($curr)) ne '' &&
0 <= $res && $res <= $#data )
{ do { $curr = $res ; &unshowValues ; } if $res != $curr ;
$Xr = 0 ;
}
elsif ( $c eq 'KEY_UP' && $curF > 0 )
{ $curF-- ; }
elsif ( $c eq 'KEY_DOWN' && $curF < $#name )
{ $curF++ ; }
elsif ( $c eq 'KEY_LEFT' && $Xr > 0 )
{ $Xr = &max($Xr-1-int(($numValueCols-2)/3),0) ; }
elsif ( $c eq 'KEY_RIGHT' && $Xr < $maxXr )
{ $Xr = &min($Xr+1+int(($numValueCols-2)/3),$maxXr) ; }
elsif ( $c eq "n" && $curr < $#data )
{ $curr++ ;
&unshowValues ;
}
elsif ( $c eq "p" && $curr > 0)
{ $curr-- ;
&unshowValues ;
}
elsif ( $c eq "/" && $curr >= 0 )
{ ($res,$sPat) = &getStrFrom('pattern:',*sPat,$#sPat) ;
if ( $res == 0 || $sPat eq '' )
{ &showStatus('no change') ; }
elsif ( ! &testPat($sPat) )
{ &showStatus($@) ; }
else
{ ($curr,$curF,$res) =
&searchNextRecord(*data,$curr,*record,$curF,$sPat) ;
&showStatus($res) ;
&unshowValues if $res eq 'found' ;
}
}
elsif ( $c eq ";" && $curr >= 0 && $#sPat >= 0 )
{ $sPat = $sPat[$#sPat] ;
if ( ! &testPat($sPat) )
{ &showStatus($@) ; }
else
{ ($curr,$curF,$res) =
&searchNextRecord(*data,$curr,*record,$curF,$sPat) ;
&showStatus($res) ;
&unshowValues if $res eq 'found' ;
}
}
else
{ $found = 0 ; }
if ( $found )
{ ; }
elsif ( $c eq "u" && $curr >= 0 )
{ $Xr = 0 ;
&showRecord(*name,*record,$#data) ;
if ( &onUpdate($c) eq 'a' )
{ $data[$curr] = $record ;
$dirty++ ;
}
else
{ &showStatus('no change') ; }
}
elsif ( $c eq "a" || ( $c eq "c" && $curr >= 0 ) )
{ if ( $c eq "a" )
{ @record = &emptyRecord($#name) ;
&unshowValues ;
}
$Xr = 0 ;
$oldF = $curF ;
$curF = 0 ;
$curr++ ;
&showRecord(*name,*record,$#data) ;
if ( &onUpdate($c) eq 'a' )
{ splice(@data,$curr,0,join($;,@record)) ;
$dirty++ ;
}
else
{ &showStatus('no change') ;
$curr-- ;
}
$curF = $oldF ;
}
elsif ( $c eq "d" && $curr >= 0 )
{ push(@ddata,splice(@data,$curr,1)) ;
&showStatus('deleted') ;
$curr = &min($curr,$#data) ;
$dirty++ ;
&unshowValues ;
}
elsif ( $c eq "t" && $curr >= 0 )
{ &showTest(*name,*pat,*record) ; }
elsif ( $c eq "T" && $curr >= 0 )
{ &showStatus('Testing All ...') ;
$curr = &showTestAll(*name,*pat,*data) ;
&unshowValues ;
}
elsif ( $c eq "O" && $#data >= 0 )
{ &showStatus('select sort keys (or finish to sort whole records)') ;
($res,@record) = &getNames(*name) ;
if ( $res )
{ &showStatus('sorting ...') ;
&unshowValues ;
($res,@errors) = &doSort(*data,*record) ;
&showStatusList(@errors) ;
do { $curr = 0 ; $dirty++ ; } if $res ;
}
else
{ &showStatus('no change') ; }
&unshowValues ;
}
elsif ( $c eq "U" && $#ddata >= 0 )
{ @vals = 0..$#ddata ;
($res,@vals) = &selectFrom('deleted records',*name,*ddata,@vals) ;
if ( $res eq 'x' )
{ &showStatus("no change") ; }
elsif ( $res eq 'a' )
{ if ( $#vals >= 0 )
{ $dirty++ ;
for $vals ( reverse sort byNum @vals )
{ push(@data,splice(@ddata,$vals,1)) ; }
$curr = &min(0,$#data) ;
&showStatus('undeleted ', $#vals+1) ;
}
else
{ &showStatus("no change") ; }
}
&unshowValues ;
}
elsif ( $c eq "E" && $#data >= 0 )
{ @vals = 0..$#data ;
($res,@vals) = &selectFrom('records to extract',*name,*data,@vals) ;
if ( $res eq 'x' )
{ &showStatus("no change") ; }
elsif ( $res eq 'a' )
{ if ( $#vals >= 0 )
{ $dirty++ ;
$db = '' ;
@ndata = () ;
for $vals ( reverse sort byNum @vals )
{ push(@ndata,splice(@data,$vals,1)) ; }
$curr = &min(0,$#data) ;
@ddata = (@ddata,@data) ;
@data = @ndata ;
&showStatus('extracted ', $#vals+1) ;
}
else
{ &showStatus("no change") ; }
}
&unshowValues ;
}
elsif ( $c eq "D" && $#data >= 0 )
{ @vals = 0..$#data ;
($res,@vals) = &selectFrom('records to delete',*name,*data,@vals) ;
if ( $res eq 'x' )
{ &showStatus("no change") ; }
elsif ( $res eq 'a' )
{ if ( $#vals >= 0 )
{ $dirty++ ;
$curr = &min(0,$#data) ;
for $vals ( reverse sort byNum @vals )
{ push(@ddata,splice(@data,$vals,1)) ; }
&showStatus('deleted ', $#vals+1) ;
}
else
{ &showStatus("no change") ; }
}
&unshowValues ;
}
elsif ( $c eq "P" )
{ ($res,$str) = &getStrFrom('at ?',*joinList,$#joinList) ;
if ( $res == 0 )
{ &showStatus('no change') ; }
else
{ &showStatus('opening ...') ;
($res,@errors) = &openDb($str,*descr1,*data1,*name1,*pat1) ;
&showStatusList(@errors) ;
if ( $res == 0 )
{ &showStatus('Peeking ...') ;
($res,@errors) = &doPeek(*name,$str,*name1,*data1) ;
&showStatusList(@errors) ;
$dirty++ if $res ;
&unshowRecord ;
}
}
}
elsif ( $c eq "R" )
{ ($res,$str) = &getStrFrom('what ?',*joinList,$#joinList) ;
if ( $res == 0 )
{ &showStatus('no change') ; }
else
{ &showStatus('opening ...') ;
($res,@errors) = &openDb($str,*descr1,*data1,*name1,*pat1) ;
&showStatusList(@errors) ;
if ( $res == 0 )
{ &showStatus('Reading ...') ;
($res,@errors) = &doRead(*name,$str,*name1,*data1) ;
&showStatusList(@errors) ;
$dirty++ if $res ;
&unshowRecord ;
}
}
}
elsif ( $c eq "K" && $#data >= 0 )
{ &showStatus('select key fields (or finish to uniq records)') ;
($res,@record) = &getNames(*name) ;
if ( $res )
{ $res1 = ( $#record < 0 )
? 'record' : 'key (' . join(',',@name[@record]) . ')' ;
&showStatus("Checking if every $res1 is uniq ...") ;
($res,@vals) = &doKeyTest(*data,*name,*record) ;
if ( $res && $#vals >= 0 )
{ $dirty++ ;
$curr = &min(0,$#data) ;
for $vals ( reverse sort byNum @vals )
{ push(@ddata,splice(@data,$vals,1)) ; }
&showStatus('deleted: ',$#vals+1,' record',$#vals?'s':'') ;
}
elsif ( $res == 1 )
{ &showStatus("every $res1 is unique") ; }
elsif ( $res == 2 )
{ &showStatus("one $res1 was not uniq") ; }
elsif ( $res )
{ &showStatus("$res1 was not uniq in ",$res-1,' cases') ; }
else
{ &showStatus("no change") ; }
}
else
{ &unshowValues ;
&showStatus("no change") ;
}
}
elsif ( $c eq "C" && $#data >= 0 )
{ @record = () ;
for ( @name ) { push(@record,$fieldExpr{$_}) ; }
$Xr = 0 ;
$curF = 0 ;
&unshowValues ;
&showRecord(*name,*record,$#data) ;
$res = &doUpdate(*updReMenu,'user',1,*testEx,*quitUpd,*retEx) ;
if ( $res eq 'a' )
{ $i = 0 ;
for ( @name ) { $fieldExpr{$_} = $record[$i] if $record[$i] ; }
continue { $i++ ; }
&showStatus("Computing ...") ;
$res = &doCompute(*name,*record,*data,*ddata) ;
$dirty++ ;
&showStatus($res) ;
}
else
{ &showStatus('no change') ; }
&unshowValues ;
}
else
{ &showStatusBeep("can't do it") ; }
}
}
unshift(@INC,pop(@INC)) ;
do 'jinx.pl' || die "can't include jinx.pl\n" ;
do 'curses.pl' || die "can't include curses.pl\n" ;
do 'cterm.pl' || die "can't include cterm.pl\n" ;
do 'screen.pl' || die "can't include screen.pl\n" ;
do 'menus.pl' || die "can't include menus.pl\n" ;
$inJinx = 1 ;
if ( $#ARGV == 0 && $ARGV[0] eq '-D' )
{ &initMenus($COLSdefault) ;
close(STDIN) ;
close(STDOUT) ;
close(STDERR) ;
$dumped = 1 ;
dump startHere ;
}
startHere: ;
if ( $dumped )
{ open(TTY,'>/dev/tty') || warn "warning: can't open /dev/tty\n" ;
open(STDIN, '<&0') || do { print TTY "can't reopen STDIN" ; exit ; } ;
open(STDOUT,'>&1') || do { print TTY "can't reopen STDOUT" ; exit ; } ;
open(STDERR,'>&2') || do { print TTY "can't reopen STDERR" ; exit ; } ;
close(TTY) ;
}
@ctermArgs = () ; $logLevel = -1 ;
while ( $#ARGV >= 0 && $ARGV[0] =~ /^-/ )
{ $OPT = shift ;
$OPT =~ s/^.// ;
if ( $OPT =~ /^L(\d+)?$/ )
{ $logLevel = $1 ;
$logFile = shift ;
push(@ctermArgs,$logFile,$logLevel) if $logFile ;
}
elsif ( $OPT eq 'D' )
{ ; }
elsif ( $OPT eq 'v' )
{ print STDERR "Jinx version 2.1, " ;
print STDERR "copyright (c) 1990, Henk P. Penning.\n" ;
print STDERR "Jinx may be copied only under the terms " ;
print STDERR "of the GNU General Public License,\na copy " ;
print STDERR "of which comes with the Jinx distribution kit.\n" ;
exit(0) ;
}
else
{ push(@errors,"$0: unknown option '$OPT'") ; }
}
for ( @errors )
{ print STDERR "$_\n" ; }
die "Usage: $0 [-L[level] log-file] [ db ... ]\n" if $#errors >= 0 ;
($res,@errors) = &testCurses ;
if ( ! $res )
{ print STDERR join("\n",@errors), "\n" ;
exit ;
}
&startCterm('-X',@ctermArgs) ;
&initCurses ;
&initEdit($curcon{'KEY_UP'}, $curcon{'KEY_DOWN'},
$curcon{'KEY_RET'}, $curcon{'KEY_TAB'},
14,16) ;
if ( defined $curfun{'editl'} )
{ &editl(2) ;
&editl($curcon{'KEY_LEFT'}) if defined $curcon{'KEY_LEFT'} ;
}
if ( defined $curfun{'editr'} )
{ &editr(6) ;
&editr($curcon{'KEY_RIGHT'}) if defined $curcon{'KEY_RIGHT'} ;
}
$keymap{2} = 'KEY_LEFT' ;
$keymap{6} = 'KEY_RIGHT' ;
$keymap{14} = 'KEY_DOWN' ;
$keymap{16} = 'KEY_UP' ;
$keymap{'h'} = 'KEY_LEFT' ;
$keymap{'l'} = 'KEY_RIGHT' ;
$keymap{'j'} = 'KEY_DOWN' ;
$keymap{'k'} = 'KEY_UP' ;
$flushOn = 1 ;
&addlog("open jinx:") ;
&addlog("logfile: " . ( $logFile ? "$logFile, level $logLevel" : 'none') ) ;
@ddata = () ;
@descr1 = () ;
@data1 = () ;
@descr2 = () ;
@data2 = () ;
@name1 = () ;
@name2 = () ;
@pat = () ;
@pat1 = () ;
@pat2 = () ;
%fieldExpr = () ;
&initMenus($COLS) unless $dumped && $COLS == $COLSdefault ;
&initParamsScreen ;
&QUIT('Get a wider terminal.') if $numInfoCols < 6 ;
&QUIT('Get a larger terminal.') if $numFieldLines < 1 ;
if ( $#ARGV < 0 )
{ @openAs = () ;
@descr = () ;
@name = () ;
@pat = () ;
}
else
{ @openAs = (@ARGV,'') ;
$str = $ARGV[$currDb++] ;
($res,@res) = &openCurrDb($str) ;
&showStatusList(@res) ;
}
&doMetaMenu ;
&quit() ;